import { Component, Node, CameraComponent, director, BufferAsset, Vec3, instantiate } from 'cc';

import { ResMgr } from '../../Framework/Scripts/Managers/ResMgr';

import { EventMgr } from '../../Framework/Scripts/Managers/EventMgr';

import { UIMgr } from '../../Framework/Scripts/Managers/UIMgr';


import { LoadPkg } from './userData/LoadPkg';
import { ThirdFreeLookCamera } from './fight/ThirdFreeLookCamera';
import { enemyBase } from './fight/enemyBase';
import { poolManager } from '../../Framework/Scripts/Managers/poolManager';
import { playerBase } from './fight/playerBase';
import { UserData } from './userData/UserData';
import { CharacterClass, constant, OBJ_TYPE } from './constant';
import { TimerMgr } from '../../Framework/Scripts/Managers/TimerMgr';
import { RandomUtils } from '../../Framework/Scripts/Utils/RandomUtils';

/** 
  周无邪出品
  本源码用于学习研究使用。
  作者联系方式：tuya7078（微信）。
 */

export class GameApp extends Component {

    public static Instance: GameApp = null;//单例
    public isBack: boolean = false//home按钮用防止连续点击
    public map: Node = null//地图
    public isGameOver: boolean = false//游戏是否开始或结束的标记
    public isFirstLoad: boolean = false//是不是第一次加载 第一次资源加载使用

    //场景根节点
    public mapRoot: Node = null//地图
    public enemyRoot: Node = null//敌军
    public friendlyRoot: Node = null//友军
    public gameRoot: Node = null//根节点
    public playerRoot: Node = null//玩家
    public wrramingRoot: Node = null//技能提示
    public skillRoot: Node = null//技能
    public bloodBar_root: Node = null//血条
    public fightTip_root: Node = null//血条数字
    public player: Node = null//玩家节点
    public playerTs: playerBase = null//玩家脚本
    public building: Node = null//城堡
    public CanvasCamera: CameraComponent = null;//2d摄像机
    public Camera: ThirdFreeLookCamera = null//3d主摄像机组件
    public trailName: string = "";//当前玩家武器特效
    public hitName: string = "";//当前玩家武器击中玩家的特效
    public arrowName: string = "";//当前玩家武器发射的弓箭数量
    public skillEnemyCount: number = 0//敌人个数
    public nowEnemyCount: number = 0//当前刷出的敌人数
    public playerData = null//玩家数据
    public level: number = 1;//当前关卡
    public enemyTimer: number = null//敌人计时器
    public friendTimer: number = null//友军计时器
    public enemyCount: number = 10//敌人总数
    public minMapCamer: CameraComponent = null//小地图摄像机
    public shopCamera: CameraComponent = null//兵种升级摄像机
    public shopShow: Node = null//兵种升级3D图鉴展示节点
    public levelArr = []  //所有关卡数据 进入游戏只生成一次
    public CamerStartPos: Vec3 = new Vec3()//3d主摄像机初始坐标


    public zone: string = null//废弃

    //敌军数据
    public levelData = {
        everyCount: null,//每个门多少个
        level: null,
        enemyCount: null,//敌人总数
        open: null,
        time: null,
        arr: null,
    }

    //当前友军数据
    public friendlyData = {


        everyCount: null,//每个门多少个
        open: null,
        time: null,
        arr: null,
    }




    onLoad(): void {

        if (GameApp.Instance === null) {
            GameApp.Instance = this;
        }
        else {
            this.destroy();
            return;
        }




    }



    //关卡配置 进入游戏时候执行一次

    private setLevelArr() {


        for (let i = 1; i <= 200; i++) {
            let level: any = {};

            // 设置敌人数量，每关增加4个，最少10个敌人，最多200个敌人
            level.enemyCount = Math.min(50, 10 + (i - 1) * 2);

            // 每5关增加一个门，最多4个门
            if (i < 3) {
                level.open = ["1"]
            } else if (i >= 3 && i < 10) {
                level.open = ["1", "2"]
            } else if (i >= 10 && i < 20) {
                level.open = ["1", "2", "3"]
            } else {
                level.open = ["1", "2", "3", "4"]
            }
            // level.open = Array.from({ length: Math.min(4, 1 + Math.floor(i / 5)) }, (_, j) => (j + 1).toString());

            // 设置敌人出怪时间，根据需要可以增加其他难度调整
            //     level.time = Math.max(3, 5 - Math.floor(i / 25));  // 出兵时间，最快三秒，每25关减少1秒
            // 设置敌人出怪时间，最慢5秒，最快2秒，每关减少0.05秒
            level.time = Math.max(2, 5 - (i - 1) * 0.05);

            // 定义敌人种类及其初始权重
            let enemyOptions = [
                { name: "altman", weight: 100 },
                { name: "axe", weight: 85 },
                { name: "javelin", weight: 65 },
                { name: "soldier", weight: 50 },
                { name: "clown", weight: 48 },
                { name: "catapult", weight: 40 },
                { name: "aula", weight: 35 },
                { name: "boomDragon", weight: 30 },
                { name: "magician", weight: 25 },
                { name: "hellFire", weight: 22 },
                { name: "dragon", weight: 15 },
            ];

            // 每3关增加一种敌人
            let availableEnemies = enemyOptions.slice(0, Math.min(enemyOptions.length, 2 + Math.floor(i / 3)));

            // 每5关增加敌人权重
            level.enemyArr = availableEnemies.map(enemy => ({
                name: enemy.name,
                weight: enemy.weight + Math.floor(i / 5) * 5  // 每5关权重增加5
            }));

            this.levelArr.push(level);


        }
    }

    //初始化
    public Init(): void {
        //先设置关卡
        this.setLevelArr()
        console.log("关卡配置完毕：", this.levelArr);
        this.gameRoot = this.node.parent.getChildByName("game")
        this.mapRoot = this.gameRoot.getChildByName("map")
        this.enemyRoot = this.gameRoot.getChildByName("enemy")
        this.friendlyRoot = this.gameRoot.getChildByName("friendly")
        this.playerRoot = this.gameRoot.getChildByName("player")
        this.wrramingRoot = this.gameRoot.getChildByName("wrraming")
        this.fightTip_root = UIMgr.Instance.uiCanvas.node.getChildByName("fightTip_root")

        this.skillRoot = this.gameRoot.getChildByName("skill")
        this.CanvasCamera = UIMgr.Instance.uiCamera

        this.Camera = this.node.parent.getChildByName("MainCamera").getComponent(ThirdFreeLookCamera)
        this.bloodBar_root = UIMgr.Instance.uiCanvas.node.getChildByName("bloodBar_root")
        this.CamerStartPos = this.Camera.node.getWorldPosition()//摄像机起始位置
        this.shopCamera = this.gameRoot.parent.getChildByName("shopCamera").getComponent(CameraComponent)
        this.minMapCamer = this.gameRoot.parent.getChildByName("minCamera").getComponent(CameraComponent)
        this.shopShow = this.gameRoot.parent.getChildByName("shopShow")
        UserData.Instance.getLocalData()
        this.synchronousData()

    }
    //游戏入口 进入大厅页面
    public enterGame() {
        director.resume()
        this.delAll()
        if (this.isFirstLoad) {
            //直接显示首页
            UIMgr.Instance.DestroyAllUIView()
            UIMgr.Instance.IE_ShowUIView("UIhome")
            return
        }
        //加载首页资源包
        UIMgr.Instance.IE_ShowUIView("UILoading")
        ResMgr.Instance.preloadResPkg(LoadPkg.Instance.pkg.enterGamePkg, (now, total) => {
            EventMgr.Instance.Emit("load", now / total)
        }, () => {
            UIMgr.Instance.DestroyAllUIView()
            this.isFirstLoad = true
            UIMgr.Instance.IE_ShowUIView("UIhome")
        })





    }


    //根据散射获取弓箭预制体  
    private getArrow(): any {
        this.arrowName = ""
        const skillData: {} = UserData.Instance.localData["playerConfig"][UserData.Instance.localData["playerType"]]["skill"]
        console.log("---------------------", skillData);

        const num: number = skillData["arrow_count"]
        switch (num) {
            case 0:
                this.arrowName = "arrowSingle"
                break;

            case 1:
                this.arrowName = "arrowSingle2"
                break;

            case 2:
                this.arrowName = "arrowSingle3"
                break;

            case 3:
                this.arrowName = "arrowSingle4"
                break;

            default:
                this.arrowName = "arrowSingle4"
                break;
        }


    }
    //获取弓箭手武器特效
    private getTrail(): any {

        this.trailName = ""
        this.hitName = ""

        //  let str: string = ""
        const skillData: {} = UserData.Instance.localData["playerConfig"][UserData.Instance.localData["playerType"]]["skill"]

        let isFire: boolean = false
        let isIce: boolean = false
        let isLight: boolean = false


        if (skillData["gongji"] > 0) {
            isFire = true   //攻击力 
        }
        if (skillData["jiansu"] > 0) {
            isIce = true    //减速   
        }
        if (skillData["baoji"] > 0) {
            isLight = true      //暴击   
        }

        //火和冰
        if ((isFire && isIce) && (!isLight)) {
            this.trailName = "arrowFireIce"
            this.hitName = "hitIce"
        }
        //火和闪电
        else if ((isFire && isLight) && (!isIce)) {
            this.trailName = "arrowLightningFire"
            this.hitName = "hitLightning"
        }
        //冰和闪电
        else if ((isIce && isLight) && (!isFire)) {
            this.trailName = "arrowLightningIce"
            this.hitName = "hitIce"
        }
        //all
        else if (isIce && isLight && isFire) {
            this.trailName = "arrowAll"
            this.hitName = "hitIce"
        } else {
            if (isFire) {
                this.trailName = "arrowFire"
                this.hitName = "hitFire"

            }
            if (isIce) {
                this.trailName = "arrowIce"
                this.hitName = "hitIce"

            }
            if (isLight) {
                this.trailName = "arrowLightning"
                this.hitName = "hitLightning"
            }
        }


    }

    //消灭敌人后减少个数
    public subEnemyCount() {

        if (this.skillEnemyCount == this.enemyCount) {
            return


        }
        this.skillEnemyCount++
        const bfb: number = this.skillEnemyCount / this.enemyCount
        EventMgr.Instance.Emit(constant.EVENT_NAME.subEnemyCount, { skillEnemyCount: this.skillEnemyCount, enemyCount: this.enemyCount })
        if (this.skillEnemyCount == this.enemyCount && bfb >= 1) {
            console.log("游戏胜利");
            this.gameWin()


        }



    }
    //游戏胜利
    public gameWin() {


        UserData.Instance.localData["level"]++

        // UserData.Instance.localData["playerConfig"][UserData.Instance.localData["playerType"]]["level"]++
        UserData.Instance.saveLocalData()

        this.stopTimer()
        poolManager.instance.clearAllPool()
        UIMgr.Instance.showUIView("GameWin")

    }
    //停止所有计时器
    public stopTimer() {
        if (this.friendTimer) {
            TimerMgr.Instance.UnSchedule(this.friendTimer)
            this.friendTimer = null
        }
        if (this.enemyTimer) {
            TimerMgr.Instance.UnSchedule(this.enemyTimer)
            this.enemyTimer = null
        }
    }
    //同步玩家数据数据
    public synchronousData() {
        //传入技能等级
        const getPlayerType: string = UserData.Instance.localData["playerType"]
        this.playerData = constant.characterConfig[getPlayerType]
        for (let key in this.playerData["config"]) {

            this.playerData["config"][key]["level"] = UserData.Instance.localData["playerConfig"][getPlayerType]["skill"][key]
        }


        //以下是仅修改基础属性
        // shengming: 200 初始血量 技能每提升一级加50
        this.playerData["shengming"] = this.playerData["oldConfig"]["shengming"] + this.playerData["config"]["shengming"]["level"] * 100

        // gongji: 50 基础攻击力  技能每提升一级+10点伤害
        this.playerData["gongji"] = this.playerData["oldConfig"]["gongji"] + this.playerData["config"]["gongji"]["level"] * 8


        // jiansu: 0,//给敌人减速 百分比  技能每提升一级加百分之5  百分之50封顶
        this.playerData["jiansu"] = this.playerData["oldConfig"]["jiansu"] + this.playerData["config"]["jiansu"]["level"] * 5

        // baoji: 10,//暴击   百分比 技能每提升一级加百分之5  百分之70封顶
        this.playerData["baoji"] = this.playerData["oldConfig"]["baoji"] + this.playerData["config"]["baoji"]["level"] * 3

        // fangyu: 0,//防御力  百分比  技能每提升一级加百分之2  百分之40封顶
        this.playerData["fangyu"] = this.playerData["oldConfig"]["fangyu"] + this.playerData["config"]["fangyu"]["level"] * 2

        // minjie: 0,//移动速度  百分比  百分之200封顶  
        this.playerData["minjie"] = this.playerData["oldConfig"]["minjie"] + this.playerData["config"]["minjie"]["level"] * 8

        //非共有属性判断职业
        switch (getPlayerType) {
            case CharacterClass.Archer:
                this.playerData["skills"]["skill4"]["cd"] = this.playerData["skills"]["skill4"]["oldCd"] - this.playerData["config"]["hudunCD"]["level"] * 2

                this.playerData["skills"]["skill1"]["cd"] = this.playerData["skills"]["skill1"]["oldCd"] - this.playerData["config"]["sanlianjiCd"]["level"] * 1

                break;

            default:
                break;
        }

        //同步友军数据
        for (let key in constant.friendlyData) {

            constant.friendlyData[key]["level"] = UserData.Instance.localData["friendlyData"][key]["level"]
            constant.friendlyData[key]["isBuy"] = UserData.Instance.localData["friendlyData"][key]["isBuy"]
        }
        //同步建筑数据
        for (let key in constant.buildData) {

            constant.buildData[key]["level"] = UserData.Instance.localData["bulidData"][key]




        }

    }
    //清空所有元素 游戏重新开始时候调用
    public delAll() {
        this.Camera.init(null, null)//清空摄像机
        //  this.Camera.node.setWorldPosition(this.CamerStartPos)
        this.bloodBar_root.destroyAllChildren()
        const arr: Node[] = this.gameRoot.children
        arr.forEach(element => {
            element.destroyAllChildren()
        });
        poolManager.instance.clearAllPool()
    }

    //提示框
    public show_tip(str: string, fun: Function = null, btnStr: string = "确定", isAD: boolean = false) {
        if (UIMgr.Instance.canvasNode.getChildByName("showTip")) {
            return
        }
        UIMgr.Instance.showUIView("showTip")
        const upData = {
            title: str,
            fun: fun,
            btnStr: btnStr,
            isAD: isAD
        }
        EventMgr.Instance.Emit(constant.EVENT_NAME.showTip, upData)

    }
    //加载框
    public showLoadUI() {
        if (UIMgr.Instance.canvasNode.getChildByName("showLoading")) {
            return
        }
        UIMgr.Instance.showUIView("showLoading")


    }
    //删除加载框
    public RemoveShowLoadUI() {

        if (UIMgr.Instance.canvasNode.getChildByName("showLoading")) {
            UIMgr.Instance.DestroyUIView("showLoading")
        }

    }
    //随机敌人
    private getRandomMonster(obj): string {
        // 定义怪物和对应的概率权重
        const monsters = obj
        // 计算总权重
        const totalWeight = monsters.reduce((sum, monster) => sum + monster.weight, 0);
        // 生成一个随机数
        let random = Math.random() * totalWeight;
        // 根据权重选择怪物
        for (const monster of monsters) {
            if (random < monster.weight) {
                return monster.name;
            }
            random -= monster.weight;
        }
        return monsters[0].name; // 默认返回，理论上不应该执行到这里
    }

    //开始游戏
    public StartGame() {
        director.resume()
        this.delAll()
        this.stopTimer()
        this.nowEnemyCount = 0
        this.node.parent.getChildByName("game").getChildByName("map").destroyAllChildren()
        this.skillEnemyCount = 0
        this.enemyCount = 0

        UIMgr.Instance.showUIView("UILoading")

        let ModelsArr: string[] = [
            "prop/coin",//金币
            "prop/heartA",//红心
            "trail/coinTrail",//拖尾
        ]

        //选择玩家
        const getPlayerType: string = UserData.Instance.localData["playerType"]
        this.playerData = constant.characterConfig[getPlayerType]
        this.synchronousData()//同步技能等级





        const AssetName: string = this.playerData["modle"]
        //加载技能特效
        for (let key in this.playerData["skills"]) {
            const skillArr: string[] = this.playerData["skills"][key]["asset"]
            if (skillArr.length > 0) {
                skillArr.forEach(element => {
                    ModelsArr.push("playerSkill/" + getPlayerType + "/" + element)
                });
            }

        }



        //如果是弓箭手加载下弓箭 临时 待整合
        if (getPlayerType == CharacterClass.Archer) {
            this.getArrow()
            if (this.arrowName != "") {
                ModelsArr.push("arrow/" + this.arrowName)
            } else {
                this.arrowName = "arrowSingle"
                ModelsArr.push("arrow/" + this.arrowName)
            }

            //导入技能特效
            this.getTrail()
            if (this.trailName != "") {
                ModelsArr.push("arrowEffects/" + this.trailName)
            } else {
                // console.log("没有特效");

            }

            if (this.hitName != "") {
                ModelsArr.push("arrowHit/" + this.hitName)

            } else {
                ModelsArr.push("arrowHit/" + "hit")
                this.hitName = "hit"

            }
        }
        //设置关卡数据
        this.level = UserData.Instance.localData["level"]

        let enemyCount: number = 10//敌人数量
        let time: number = 0.5//间隔时间默认0.5
        let enemyArr = []//随机敌人类型
        let open: string[] = new Array()//开启几个传送门



        if (this.levelArr.length == 0) {
            this.setLevelArr()
        }
        //    console.log(this.levelArr);

        // 处理关卡索引，避免越界
        let level_i: number = this.level - 1;
        if (level_i >= this.levelArr.length) {
            level_i = this.levelArr.length - 1;
        }




        const myLevelData: any = this.levelArr[level_i]
        console.log("我的关卡", myLevelData);

        enemyCount = myLevelData.enemyCount
        open = myLevelData.open
        time = myLevelData.time
        enemyArr = myLevelData.enemyArr
        this.enemyCount = enemyCount * open.length//敌人总数



        this.levelData.level = this.level
        this.levelData.enemyCount = this.enemyCount
        this.levelData.open = open
        this.levelData.time = time
        this.levelData.arr = enemyArr
        this.levelData.everyCount = enemyCount


        console.log("关卡数据：====", myLevelData);




        //友军类型
        const f_Arr = UserData.Instance.localData["friendlyData"]

        const a: string[] = new Array()
        for (let key in f_Arr) {
            if (f_Arr[key].isBuy === true) {
                a.push(key)
            }
        }
        this.friendlyData.arr = a

        this.friendlyData.open = this.levelData.open//和敌人出生点一致
        this.friendlyData.time = 15 - (constant.buildData.friendly.level * constant.buildData.friendly.add)
        console.log("我方出兵速度", this.friendlyData.time);
        if (this.friendlyData.time < 3) {
            this.friendlyData.time = 3
        }



        this.friendlyData.everyCount = Math.floor(this.levelData.everyCount/4)  //是敌人兵力的四分之一
        if (this.friendlyData.everyCount < 1) {
            this.friendlyData.everyCount = 1
        }

        console.log("我方士兵人数" + this.friendlyData.everyCount);

        //合并数组  
        const arr1 = this.friendlyData.arr
        let arr2 = new Array()
        this.levelData.arr.forEach(element => {
            arr2.push(element.name)
        });

        const mergedArray = Array.from(new Set([...arr1, ...arr2]));
        //添加敌人资源

        LoadPkg.Instance.pkg.startGamePkg.enemy[0].urls.length = 0
        mergedArray.forEach(element => {
            LoadPkg.Instance.pkg.startGamePkg.enemy[0].urls.push(element)
        });


        ModelsArr.push("player/" + AssetName)
        ModelsArr.push("warming/Laser")
        ModelsArr.push("warming/Circle")
        ModelsArr.push("map/map1")
        LoadPkg.Instance.pkg.startGamePkg.prefab[0].urls.length = 0
        LoadPkg.Instance.pkg.startGamePkg.prefab[0].urls = ModelsArr

        //加载地图
        ResMgr.Instance.preloadResPkg(LoadPkg.Instance.pkg.startGamePkg, (now, total) => {
            //   console.log("百分比：", now / total);
            EventMgr.Instance.Emit("load", now / total)
        }, () => {
            //设置地图
            this.isGameOver = false

            this.scheduleOnce(() => {

                mergedArray.forEach(element => {
                    for (let i = 0; i < 10; i++) {
                        const n = instantiate(ResMgr.Instance.getAsset("enemy", element))
                        poolManager.instance.putNode(n)

                    }
                });

                this.map = poolManager.instance.getNode(ResMgr.Instance.getAsset("prefab", "map/map1"), this.mapRoot)



                this.player = poolManager.instance.getNode(ResMgr.Instance.getAsset("prefab", "player/" + AssetName), this.playerRoot)
                this.player.setWorldPosition(this.map.getChildByName("playerPos").getWorldPosition())
                this.playerTs = this.player.getComponent(playerBase)
                if (this.playerTs) {
                    this.playerTs.up_arrowInHand()
                }
                this.Camera.init(this.player, this.player)//摄像机跟随
                this.playerTs.init()








                this.building = this.map.getChildByName("home")














                UIMgr.Instance.DestroyAllUIView()
                UIMgr.Instance.IE_ShowUIView("UIstart")

                //开始刷敌人


                this.enemyTimer = TimerMgr.Instance.Schedule(() => {
                    let t: number = 0
                    // 
                    this.levelData.open.forEach(element => {
                        t += 0.5
                        const time: number = TimerMgr.Instance.ScheduleOnce(() => {
                            TimerMgr.Instance.UnSchedule(time)
                            //刷敌人
                            if (this.enemyTimer && this.map) {

                                const enemyName: string = this.getRandomMonster(this.levelData.arr)



                                const enemy: Node = poolManager.instance.getNode(ResMgr.Instance.getAsset("enemy", enemyName), this.enemyRoot)
                                const pos: Vec3 = this.map.getChildByName("openDoor").getChildByName(element).getWorldPosition()
                                enemy.setWorldPosition(pos.x, pos.y, pos.z)

                                const ts: enemyBase = enemy.getComponent(enemyBase)
                                if (ts) {

                                    this.nowEnemyCount++
                                    ts.openNum = parseInt(element, 10);
                                    let id: number = null



                                    ts.init(OBJ_TYPE.enemy, id, 0.8)



                                }
                            }

                        }, this, t)

                    });

                }, this, this.levelData.everyCount, this.levelData.time, this.levelData.time)









                //开始刷友军


                if (this.friendlyData.arr.length > 0) {
                    this.friendTimer = TimerMgr.Instance.Schedule(() => {
                        let t: number = 0
                        this.friendlyData.open.forEach(element => {
                            t += 0.5
                            const time: number = TimerMgr.Instance.ScheduleOnce(() => {
                                TimerMgr.Instance.UnSchedule(time)
                                if (this.friendTimer && this.map) {
                                    const r2: number = RandomUtils.getRandomInt(0, this.friendlyData.arr.length - 1)


                                    const friendName: string = this.friendlyData.arr[r2]




                                    const friend: Node = poolManager.instance.getNode(ResMgr.Instance.getAsset("enemy", friendName), this.friendlyRoot)
                                    const pos2: Vec3 = this.map.getChildByName("friendOpenDoor").getChildByName(element).getWorldPosition()

                                    friend.setWorldPosition(pos2.x, pos2.y, pos2.z)
                                    const ts2: enemyBase = friend.getComponent(enemyBase)
                                    if (ts2) {
                                        ts2.openNum = parseInt(element, 10);


                                        let id: number = null



                                        ts2.init(OBJ_TYPE.friendly, id, 0.8)


                                    }
                                }

                            }, this, t)

                        });


                    }, this, this.friendlyData.everyCount, this.friendlyData.time, this.levelData.time + 2)
                }






            }, 0.8)


        })


    }

    update(dt) {


    }
}


